package cn.yeziji.forum.service.impl;

import cn.yeziji.forum.basic.netty.Message;
import cn.yeziji.forum.basic.netty.chat.ChatMessage;
import cn.yeziji.forum.bo.chatroom.PrivateChatRecordsBO;
import cn.yeziji.forum.common.ForumPageResult;
import cn.yeziji.forum.common.key.ChatroomCacheKey;
import cn.yeziji.forum.common.key.MessageKey;
import cn.yeziji.forum.common.key.NoticeCacheKey;
import cn.yeziji.forum.dao.intf.ForumUserDao;
import cn.yeziji.forum.dao.iquery.ChatroomQuery;
import cn.yeziji.forum.dto.user.UserFocusOrFansListPagingDTO;
import cn.yeziji.forum.entity.ForumChatroomEntity;
import cn.yeziji.forum.entity.ForumUserEntity;
import cn.yeziji.forum.mapper.ForumChatroomMapper;
import cn.yeziji.forum.service.PrivateChatService;
import cn.yeziji.forum.utils.ListsCollect;
import cn.yeziji.forum.utils.RedisUtils;
import cn.yeziji.forum.utils.StrUtils;
import cn.yeziji.forum.utils.TimeUtils;
import cn.yeziji.forum.vo.chatroom.PrivateChatContactVO;
import cn.yeziji.forum.vo.user.UserMsgVO;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 私聊聊天室数据处理实现类
 *
 * @author gzkemays
 * @since 2022/12/02 5:57 PM
 */
@Service
@Slf4j
public class PrivateChatServiceImpl implements PrivateChatService {
  @Resource ForumChatroomMapper chatroomMapper;
  @Resource ForumUserDao userDao;

  @Resource RedisTemplate<String, Object> redisTemplate;

  @Override
  public List<PrivateChatContactVO> getUserContact(UserFocusOrFansListPagingDTO pagingDTO) {
    RedisUtils redisUtils = new RedisUtils(redisTemplate);
    // 获取粉丝和关注的用户列表
    ForumPageResult<UserMsgVO> focusAndFansUserMsg = userDao.getFocusAndFansUserMsg(pagingDTO);
    // 构建 set 去重
    Set<PrivateChatContactVO> set =
        new HashSet<>(
            PrivateChatContactVO.converterPrivateChatContactVos(focusAndFansUserMsg.getData()));
    // 获取聊过天的用户，从数据库中获取
    List<String> focusAndFans =
        set.stream().map(PrivateChatContactVO::getNickname).collect(Collectors.toList());
    List<ForumChatroomEntity> entities =
        chatroomMapper.listEntity(
            ChatroomQuery.getChatroomByNicknameGroupByChatroom(pagingDTO.getNickname()));
    String userNickname = pagingDTO.getNickname();
    for (ForumChatroomEntity entity : entities) {
      String to = entity.getTo(), from = entity.getFrom();
      // 只有其中之一能够满足
      if (!Objects.equals(to, userNickname) && !focusAndFans.contains(to)) {
        set.add(new PrivateChatContactVO(userDao.getUserMsg(to)));
        focusAndFans.add(to);
      } else if (!Objects.equals(from, userNickname) && !focusAndFans.contains(from)) {
        set.add(new PrivateChatContactVO(userDao.getUserMsg(from)));
        focusAndFans.add(from);
      }
    }
    ForumUserEntity fromEntity = userDao.selectUserByNickName(userNickname);
    for (PrivateChatContactVO vo : set) {
      // 构建预期聊天室
      ForumUserEntity toEntity = userDao.selectUserByNickName(vo.getNickname());
      String chatroom = buildChatroom(toEntity.getUsername(), fromEntity.getUsername());
      log.info("查找 {} 中最后一条记录时间", chatroom);
      // 先从缓存中获取，如果没有，再从数据库获取
      if (redisUtils.hasKey(ChatroomCacheKey.ONLINE_PRIVATE_CHAT_KEY + chatroom)) {
        List<ChatMessage> chatMessages =
            ListsCollect.objCollect(
                    redisUtils.list0Range(ChatroomCacheKey.ONLINE_PRIVATE_CHAT_KEY + chatroom),
                    ChatMessage.class)
                .orElseEmpty();
        log.info("缓存中有 {} 的聊天记录", chatroom);
        // 获取最新的聊天记录
        Optional<ChatMessage> max =
            chatMessages.stream().max(Comparator.comparing(ChatMessage::getPublishTime));
        if (max.isPresent()) {
          ChatMessage chatMessage = max.get();
          vo.setLastChat(chatMessage.getText());
          vo.setLastChatDate(
              StrUtils.dateToStr(TimeUtils.COMMON_MINUTE_PATTERN, chatMessage.getPublishTime()));
        }
      } else {
        // 缓存没有对应的聊天室，开始从数据库中查找
        chatroomMapper
            .findOne(
                ChatroomQuery.getLastMsgByNickname(chatroom),
                map -> {
                  PrivateChatContactVO temp = new PrivateChatContactVO();
                  temp.setLastChat((String) map.get("context"));
                  temp.setLastChatDate(
                      StrUtils.dateToStr(
                          TimeUtils.COMMON_MINUTE_PATTERN, (Date) map.get("createTime")));
                  return temp;
                })
            .ifPresent(
                (temp) -> {
                  vo.setLastChat(temp.getLastChat());
                  vo.setLastChatDate(temp.getLastChatDate());
                });
      }
    }
    // 先获取所有未读
    List<Message> messages =
        ListsCollect.objCollect(
                redisUtils.list0Range(NoticeCacheKey.UN_READ + fromEntity.getUsername()),
                Message.class)
            .orElseEmpty();
    if (!messages.isEmpty()) {
      // 获取未读的数据
      List<Message> unread =
          messages.stream()
              .filter(msg -> msg.getType() == MessageKey.PRIVATE_CHAT_FLAG)
              .collect(Collectors.toList());
      for (PrivateChatContactVO vo : set) {
        for (Message message : unread) {
          ChatMessage chatMessage = JSON.parseObject(message.getContext(), ChatMessage.class);
          if (chatMessage.getFrom() != null) {
            if (vo.getNickname().equals(chatMessage.getFrom().getNickname())) {
              vo.noticeNumberAdd();
            }
          }
          log.info("chat message -> {}", chatMessage);
        }
      }
    }
    // 获取最后一条聊天记录
    return new ArrayList<>(set);
  }

  @Override
  public List<ChatMessage> getChatroomRecords(String chatroom) {
    RedisUtils redisUtils = new RedisUtils(redisTemplate);
    // 缓存中的聊天记录
    List<ChatMessage> onlineTranscript =
        ListsCollect.objCollect(
                redisUtils.list0Range(ChatroomCacheKey.ONLINE_PRIVATE_CHAT_KEY + chatroom),
                ChatMessage.class)
            .orElseEmpty();
    Set<ChatMessage> set = new HashSet<>(onlineTranscript);
    // 数据库中的聊天记录
    List<PrivateChatRecordsBO> bos =
        chatroomMapper.listPoJos(
            PrivateChatRecordsBO.class, ChatroomQuery.getRecordsAndUserMsgByChatroomName(chatroom));
    for (PrivateChatRecordsBO entity : bos) {
      set.add(entity.buildChatMessage());
    }
    return set.stream()
        .sorted(Comparator.comparing(ChatMessage::getPublishTime))
        .collect(Collectors.toList());
  }
  /**
   * 构建私聊聊天室
   *
   * @param to 对话用户的用户名
   * @param from 发送对话的用户名
   * @return 用户名聊天室
   */
  public String buildChatroom(String to, String from) {
    if (StringUtils.isNotBlank(to) && StringUtils.isNotBlank(from)) {
      String[] split = (to + "&" + from).split("&");
      Arrays.sort(split);
      return split[0] + "&" + split[1];
    }
    throw new IllegalArgumentException("参数有误");
  }
}
